#vue pagination axios
Explore tagged Tumblr posts
laravelvuejs · 6 years ago
Text
Vuejs, Nodejs y Mongodb Paginación - VueJs
Vuejs, Nodejs y Mongodb Paginación – VueJs
Vuejs, Nodejs y Mongodb Paginación – VueJs
[ad_1]
Aprende a crear una páginacion de articulos en el frontend usando Vuejs como framework de Javascript, y Nodejs junto a Mongodb como tecnologías del Backend. En este ejemplo desarrollaremos una API sencilla que envie datos al navegador, y las páginaremos usando Vue.
CÓDIGO DEL CURSO https://github.com/FaztWeb/vuejs-node-pagination
CURSO DE JAVASCRIPT
View On WordPress
1 note · View note
itsmetacentric · 6 years ago
Link
base64 image validation in laravel, laravel axios get request, the ultimate vuejs and laravel crud tutorial, vue file upload tutorial, laravel vue file upload, vue js file upload laravel, laravel file upload vue, laravel vue axios file upload,laravel vue js crud example, laravel vue js pagination, laravel vue js tutorial, form validation vue js
0 notes
mbaljeetsingh · 7 years ago
Text
Building a Vue SPA with Laravel Part 3
News / February 16, 2018
Building a Vue SPA with Laravel Part 3
We will continue building our Vue SPA with Laravel by showing you how to load asynchronous data before the vue-router enters a route.
We left off in Building a Vue SPA With Laravel Part 2 finishing a UsersIndex Vue component which loads users from an API asynchronously. We skimped on building a real API backed by the database and opted for fake data in the API response from Laravel’s factory() method.
If you haven’t read Part 1 and Part 2 of building a Vue SPA with Laravel, I suggest you start with those posts first and then come back. I’ll be waiting for you!
In this tutorial we are also going to swap out our fake /users endpoint with a real one powered by a database. I prefer to use MySQL, but you can use whatever database driver you want!
Our UsersIndex.vue router component is loading the data from the API during the created() lifecycle hook. Here’s what our fetchData() method looks like at the conclusion of Part 2:
created() { this.fetchData(); }, methods: { fetchData() { this.error = this.users = null; this.loading = true; axios .get('/api/users') .then(response => { this.loading = false; this.users = response.data; }).catch(error => { this.loading = false; this.error = error.response.data.message || error.message; }); } }
I promised that I’d show you how to retrieve data from the API before navigating to a component, but before we do that we need to swap our API out for some real data.
Creating a Real Users Endpoint
We are going to create a UsersController from which we return JSON data using Laravel’s new API resources introduced in Laravel 5.5.
Before we create the controller and API resource, let’s first set up a database and seeder to provide some test data for our SPA.
The User Database Seeder
We can create a new users seeder with the make:seeder command:
php artisan make:seeder UsersTableSeeder
The UsersTableSeeder is pretty simple right now—we just create 50 users with a model factory:
<?php use Illuminate\Database\Seeder; class UsersTableSeeder extends Seeder { public function run() { factory(App\User::class, 50)->create(); } }
Next, let’s add the UsersTableSeeder to our database/seeds/DatabaseSeeder.php file:
<?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $this->call([ UsersTableSeeder::class, ]); } }
We can’t apply this seeder without first creating and configuring a database.
Configuring a Database
It’s time to hook our Vue SPA Laravel application up to a real database. You can use SQLite with a GUI like TablePlus or MySQL. If you’re new to Laravel, you can go through the extensive documentation on getting started with a database.
If you have a local MySQL instance running on your machine, you can create a new database rather quickly from the command line with the following (assuming you don’t have a password for local development):
mysql -u root -e"create database vue_spa;" # or you could prompt for the password with the -p flag mysql -u root -e"create database vue_spa;" -p
Once you have the database, in the .env file configure the DB_DATABASE=vue_spa. If you get stuck, follow the documentation which should make it easy to get your database working.
Once you have the database connection configured, you can migrate your database tables and add seed data. Laravel ships with a Users table migration that we are using to seed data:
# Ensure the database seeders get auto-loaded composer dump-autoload php artisan migrate:fresh --seed
You can also use the separate artisan db:seed command if you wish! That’s it; you should have a database with 50 users that we can query and return via the API.
The Users Controller
If you recall from Part 2, the fake /users endpoint found in the routes/api.php file looks like this:
Route::get('/users', function () { return factory('App\User', 10)->make(); });
Let’s create a controller class, which also gives us the added benefit of being able to use php artisan route:cache in production, which is not possible with closures. We’ll create both the controller and a User API resource class from the command line:
php artisan make:controller Api/UsersController php artisan make:resource UserResource
The first command is adding the User controller in an Api folder at app/Http/Controllers/Api, and the second command adds UserResource to the app/Http/Resources folder.
Here’s the new routes/api.php code for our controller and Api namespace:
Route::namespace('Api')->group(function () { Route::get('/users', 'UsersController@index'); });
The controller is pretty straightforward; we are returning an Eloquent API resource with pagination:
<?php namespace App\Http\Controllers\Api; use App\User; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\Http\Resources\UserResource; class UsersController extends Controller { public function index() { return UserResource::collection(User::paginate(10)); } }
Here’s an example of what the JSON response will look like once we wire up the UserResource with API format:
{ "data":[ { "name":"Francis Marquardt", "email":"[email protected]" }, { "name":"Dr. Florine Beatty", "email":"[email protected]" }, ... ], "links":{ "first":"http:\/\/vue-router.test\/api\/users?page=1", "last":"http:\/\/vue-router.test\/api\/users?page=5", "prev":null, "next":"http:\/\/vue-router.test\/api\/users?page=2" }, "meta":{ "current_page":1, "from":1, "last_page":5, "path":"http:\/\/vue-router.test\/api\/users", "per_page":10, "to":10, "total":50 } }
It’s fantastic that Laravel provides us with the pagination data and adds the users to a data key automatically!
Here’s the UserResource class:
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\Resource; class UserResource extends Resource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ 'name' => $this->name, 'email' => $this->email, ]; } }
The UserResource transforms each User model in the collection to an array and provides the UserResource::collection() method to transform a collection of users into a JSON format.
At this point, you should have a working /api/users endpoint that we can use with our SPA, but if you are following along, you will notice that our new response format breaks the component.
Fixing the UsersIndex Component
We can quickly get our UsersIndex.vue Component working again by adjusting the then() call to reference the data key where our user data now lives. It might look at little funky at first, but response.data is the response object, so the user data can be set like the following:
this.users = response.data.data;
Here’s the adjusted fetchData() method that works with our new API:
fetchData() { this.error = this.users = null; this.loading = true; axios .get('/api/users') .then(response => { this.loading = false; this.users = response.data.data; }).catch(error => { this.loading = false; this.error = error.response.data.message || error.message; }); }
Fetching Data Before Navigation
Our component is working with our new API, and it’s an excellent time to demonstrate how you might fetch users before navigation to the component occurs.
With this approach, we fetch the data and then navigate to the new route. We can accomplish this by using the beforeRouteEnter guard on the incoming component. An example from the vue-router documentation looks like this:
beforeRouteEnter (to, from, next) { getPost(to.params.id, (err, post) => { next(vm => vm.setData(err, post)) }) },
Check the documentation for the complete example, but suffice it to say that we will asynchronously get the user data, once complete, and only after completion, we trigger next() and set the data on our component (the vm variable).
Here’s what a getUsers function might look like to asynchronously get users from the API and then trigger a callback into the component:
const getUsers = (page, callback) => { const params = { page }; axios .get('/api/users', { params }) .then(response => { callback(null, response.data); }).catch(error => { callback(error, error.response.data); }); };
Note that the method doesn’t return a Promise, but instead triggers a callback on completion or failure. The callback passes to arguments, an error, and the response from the API call.
Our getUsers() method accepts a page variable which ends up in the request as a query string param. If it’s null (no page passed in the route), then the API will automatically assume page=1.
The last thing I’ll point out is the const params value. It will effectively look like this:
{ params: { page: 1 } }
And here’s how our beforeRouteEnter guard uses the getUsers function to get async data and then set it on the component while calling next():
beforeRouteEnter (to, from, next) { const params = { page: to.query.page }; getUsers(to.query.page, (err, data) => { next(vm => vm.setData(err, data)); }); },
This piece is the callback argument in the getUses() call after the data is returned from the API:
(err, data) => { next(vm => vm.setData(err, data)); }
Which is then called like this in getUsers() on a successful response from the API:
callback(null, response.data);
The beforeRouteUpdate
When the component is in a rendered state already, and the route changes, the beforeRouteUpdate gets called, and Vue reuses the component in the new route. For example, when our users navigate from /users?page=2 to /users?page=3.
The beforeRouteUpdate call is similar to beforeRouteEnter. However, the former has access to this on the component, so the style is slightly different:
// when route changes and this component is already rendered, // the logic will be slightly different. beforeRouteUpdate (to, from, next) { this.users = this.links = this.meta = null getUsers(to.query.page, (err, data) => { this.setData(err, data); next(); }); },
Since the component is in a rendered state, we need to reset a few data properties before getting the next set of users from the API. We have access to the component. Therefore, we can call this.setData() (which I have yet to show you) first, and then call next() without a callback.
Finally, here’s the setData method on the UsersIndex component:
setData(err, { data: users, links, meta }) { if (err) { this.error = err.toString(); } else { this.users = users; this.links = links; this.meta = meta; } },
The setData() method uses object destructuring to get the data, links and meta keys coming from the API response. We use the data: users to assign data to the new variable name users for clarity.
Tying the UsersIndex All Together
I’ve shown you pieces of the UsersIndex component, and we are ready to tie it all together, and sprinkle on some very basic pagination. This tutorial isn’t showing you how to build pagination, so you can find (or create) fancy pagination of your own!
Pagination is an excellent way to show you how to navigate around an SPA with vue-router programmatically.
Here’s the full component with our new hooks and methods to get async data using router hooks:
<template> <div class="users"> <div v-if="error" class="error"> <p></p> </div> <ul v-if="users"> <li v-for="{ id, name, email } in users"> <strong>Name:</strong> , <strong>Email:</strong> </li> </ul> <div class="pagination"> <button :disabled="! prevPage" @click.prevent="goToPrev">Previous</button> <button :disabled="! nextPage" @click.prevent="goToNext">Next</button> </div> </div> </template> <script> import axios from 'axios'; const getUsers = (page, callback) => { const params = { page }; axios .get('/api/users', { params }) .then(response => { callback(null, response.data); }).catch(error => { callback(error, error.response.data); }); }; export default { data() { return { users: null, meta: null, links: { first: null, last: null, next: null, prev: null, }, error: null, }; }, computed: { nextPage() { if (! this.meta || this.meta.current_page === this.meta.last_page) { return; } return this.meta.current_page + 1; }, prevPage() { if (! this.meta || this.meta.current_page === 1) { return; } return this.meta.current_page - 1; }, paginatonCount() { if (! this.meta) { return; } const { current_page, last_page } = this.meta; return `${current_page} of ${last_page}`; }, }, beforeRouteEnter (to, from, next) { getUsers(to.query.page, (err, data) => { next(vm => vm.setData(err, data)); }); }, // when route changes and this component is already rendered, // the logic will be slightly different. beforeRouteUpdate (to, from, next) { this.users = this.links = this.meta = null getUsers(to.query.page, (err, data) => { this.setData(err, data); next(); }); }, methods: { goToNext() { this.$router.push({ query: { page: this.nextPage, }, }); }, goToPrev() { this.$router.push({ name: 'users.index', query: { page: this.prevPage, } }); }, setData(err, { data: users, links, meta }) { if (err) { this.error = err.toString(); } else { this.users = users; this.links = links; this.meta = meta; } }, } } </script>
If it’s easier to digest, here’s the UsersIndex.vue as a GitHub Gist.
There are quite a few new things here, so I’ll point out some of the more important points. The goToNext() and goToPrev() methods demonstrate how you navigate with vue-router using this.$router.push:
this.$router.push({ query: { page: `${this.nextPage}`, }, });
We are pushing a new page to the query string which triggers beforeRouteUpdate. I also want to point out that I’m showing you a <button> element for the previous and next actions, primarily to demonstrate programmatically navigating with vue-router, and you would likely use <router-link /> to automatically navigate between paginated routes.
I have introduced three computed properties (nextPage, prevPage, and paginatonCount) to determine the next and previous page numbers, and a paginatonCount to show a visual count of the current page number and the total page count.
The next and previous buttons use the computed properties to determine if they should be disabled, and the “goTo” methods use these computed properties to push the page query string param to the next or previous page. The buttons are disabled when a next or previous page is null at the boundaries of the first and last pages.
There’s probably a bit of redundancy in the code, but this component illustrates using vue-router for fetching data before entering a route!
Don’t forget to make sure you build the latest version of your JavaScript by running Laravel Mix:
# NPM npm run dev # Watch to update automatically while developing npm run watch # Yarn yarn dev # Watch to update automatically while developing yarn watch
Finally, here’s what our SPA looks like after we update the complete UsersIndex.vue component:
What’s Next
We now have a working API with real data from a database, and a simple paginated component which uses Laravel’s API model resources on the backend for simple pagination links and wrapping the data in a data key.
Next, we will work on creating, editing, and deleting users. A /users resource would be locked down in a real application, but for now, we are just building CRUD functionality to learn how to work with vue-router to navigate and pull in data asynchronously.
We could also work on abstracting the axios client code out of the component, but for now, it’s simple, so we’ll leave it in the component until Part 4. Once we add additional API features, we’ll want to create a dedicated module for our HTTP client.
via Laravel News http://ift.tt/2BxHnhd
0 notes
programmingbiters-blog · 7 years ago
Photo
Tumblr media
New Post has been published on http://programmingbiters.com/single-page-application-starter-kit-with-laravel-and-vue-js/
Single Page Application Starter Kit with Laravel and Vue.js
spa-starter-kit
Codecast’s Single Page Application Starter Kit is a package which contains two separate projects to act as a starting point for a Single Page Application: a Vue.js project (created with vue-cli and webpack template) and a Laravel 5.3 project. They’re not just freshly created projects but a fully working application that can be modified and expanded to become your own application.
Features
Vue.js 2.0 project create with vue-cli with webpack template
Centralized state management with Vuex
Route management with Vue-router
Authentication with JWT
Keep user signed in using local stored info
HTTP requests with Axios
Pagination integrated with Laravel’s LengthAwarePaginator
Alerts and Confirmation Alerts provided by SweetAlert
Server side
Laravel 5.3
Authentication with JWT
Make sure you have installed Node and Yarn (latest versions) as well as PHP 7 and MySQL.
Check it out on GitHub and a demo.
!function(f,b,e,v,n,t,s)if(f.fbq)return;n=f.fbq=function()n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments);if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '252788801793222', em: 'insert_email_variable,' ); fbq('track', 'PageView');
قالب وردپرس
0 notes
laravelvuejs · 8 years ago
Text
Single Page Application with Laravel 5.3 and Vue.js 2.1.x
Single Page Application with Laravel 5.3 and Vue.js 2.1.x
[ad_1]
Single Page Application with Laravel 5.3 and Vue.js 2.1.x. Refer the source code for better understanding.
Frameworks and Libraries: – Laravel 5.3 – Vue.js 2.1.x – Vue Router – axios
Provides: – CRUD – Single Page Application – Pagination – Sorting by columns – Advance filter – Filter relations
– – –
Source Code: https://github.com/codekerala/spa-laravel-vuejs
– – –
You should follow Code…
View On WordPress
0 notes
mbaljeetsingh · 8 years ago
Text
Implement a Favoriting Feature Using Laravel and Vue.js
These days, various web applications are in one way or the other implementing a kind of favorite/like/recommend feature on the websites. These can be seen on sites like Medium, Facebook, Laracasts, and even here on scotch.io and school.scotch.io.
In this tutorial, I'll be showing you how to implement a favorites feature using Vue.js in your Laravel application. Though we'll be using the term favorites in this tutorial, this can be replaced with likes, recommends depending on your application.
What We'll Be Building
We'll be building a simple Posts app. This app will comprise of users and posts. Users will be able to create posts and as well mark posts as favorites. Finally, users will be able to see all the posts they marked as favorites.
The app will have a User model and a Post model, there will be an authentication system which will allow only authenticated users mark/unmark posts as favorites. We'll make use of VueJs and Axios to make marking/un-marking posts as favorites dynamic, that is without reloading the page.
Before we start building, let's take a quick look at what the Posts app will look like when we are done.
Let's Get started
We'll start by creating a new Laravel project, the name of the project will be laravel-vue-favorite.
laravel new laravel-vue-favorite
This will create a new Laravel 5.4 (which is the current version as at the time of this tutorial) project.
Installing NPM Dependencies
In a fresh installation of Laravel, Laravel provides some frontend frameworks and libraries with some basic setup to integrate these packages together. Among the frameworks and libraries are Bootstrap, VueJs and Axios, which we will be using in this tutorial. But we still need to install these dependencies through NPM:
npm install
Also, we'll make use of Laravel Mix to compile and build our CSS and JavaScript. The command above will also install all Laravel Mix dependencies.
Models And Migrations
For our Posts app, we'll need a User model (which comes with Laravel), a Post model and a Favorite model and their respective migration files.
php artisan make:model Post -m php artisan make:model Favorite -m
These will create a Post model and a Favorite model along with their migration files respectively. Open the posts table migration file and update the up() with:
/** * Define posts table schema */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->string('title'); $table->text('body'); $table->timestamps(); }); }
The posts table will contain an id, user_id (ID of the user that created the post), title, body, and some timestamps columns.
Next, open the favorites table migration file and update the up() with:
/** * Define favorites table schema */ public function up() { Schema::create('favorites', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned(); $table->integer('post_id')->unsigned(); $table->timestamps(); }); }
The favorites table will be a pivot table. It will contain two columns: user_id which will hold the ID of the user that favorited a post and post_id which will the ID of the post that was favorited.
For the users table migration, we'll be using the default Laravel provided.
Before we run our migrations, let's setup our database. Add your database details to the .env file:
DB_DATABASE=laravue DB_USERNAME=root DB_PASSWORD=root
Remember to update with your own database details. Now we can go on and run our migrations:
php artisan migrate
Database Seeder
We'll also generate some seed data which we can test our app with. To generate dummy data, we'll make use of Laravel Model Factories. Laravel model factories make use of the Faker PHP library.
We'll generate dummy data of Users and Posts. When you open the database/factories/ModelFactory.php file, you will see that Laravel provides a User model factory, which means we only need to create a Post model factory. Add the snippets below to database/factories/ModelFactory.php just after the User model factory:
// database/factories/ModelFactory.php $factory->define(App\Post::class, function (Faker\Generator $faker) { // Get a random user $user = \App\User::inRandomOrder()->first(); // generate fake data for post return [ 'user_id' => $user->id, 'title' => $faker->sentence, 'body' => $faker->text, ]; });
Let's quickly run through the code. Remember from our posts table migration, we defined that a post must have a user ID. So, we get a random user and assign the user_id of a post to the ID of the random user, then we use Faker to generate the title and body of the post.
With our model factories done, let's move on to create our database seeder classes by running these commands:
php artisan make:seeder UsersTableSeeder php artisan make:seeder PostsTableSeeder
Open database/seeds/UsersTableSeeder.php and update the run() with:
// database/seeds/UsersTableSeeder.php /** * Run the database seeds to create users. * * @return void */ public function run() { factory(App\User::class, 5)->create(); }
This will create 5 different users with dummy data when the seeder is run. We'll do the same for Posts. Open database/seeds/PostsTableSeeder.php and update the run() with:
// database/seeds/PostsTableSeeder.php /** * Run the database seeds to create posts. * * @return void */ public function run() { factory(App\Post::class, 10)->create(); }
This will create 10 different posts with dummy data when the seeder is run.
Before we run the database seeders, let's update the database/seeds/DatabaseSeeder.php which is provided by default:
// database/seeds/DatabaseSeeder.php /** * Run the database seeds. * * @return void */ public function run() { $this->call(UsersTableSeeder::class); $this->call(PostsTableSeeder::class); }
Now we can run the database seeders:
php artisan db:seed
You should now see some dummy data in your database.
Authenticating Users
Before a user can mark a post has favorite, the user must be logged in. So we need a kind of authentication system. Luckily for us, Laravel got our back on this. We'll use the artisan make:auth command to scaffold an authentication system.
php artisan make:auth
This will create all of the necessary routes and views for authentication. We can go and register as a user, which we will use to test the functionality of the application we are building.
Defining Our Routes
Let's define the routes of our application. Open routes/web.php and update with below:
// routes/web.php Auth::routes(); Route::get('/', 'PostsController@index'); Route::post('favorite/{post}', 'PostsController@favoritePost'); Route::post('unfavorite/{post}', 'PostsController@unFavoritePost'); Route::get('my_favorites', 'UsersController@myFavorites')->middleware('auth');
The routes are pretty straightforward. Auth routes that Laravel created when we ran the make:auth command. A route to the homepage that will list all posts, two other routes for favoriting and unfavoriting posts. Lastly, a route that displays all posts that have been marked as favorites by a user. This route will be accessible to only authenticated users.
When a user registers or login, Laravel will redirect them to the /home route by default. Since we have removed the /home route that Laravel created when we ran make:auth. We need to update the redirectTo property of both app/Http/Controllers/Auth/LoginController.php and app/Http/Controllers/Auth/RegisterController.php to:
protected $redirectTo = '/';
Defining Users To Favorite Posts Relationship
Since a user can mark many posts as favorites and a post can be marked as favorites by many users, the relationship between users and favorite posts will be a many to many relationships. To define this relationship, open the User model and add a favorites():
// app/User.php /** * Get all of favorite posts for the user. */ public function favorites() { return $this->belongsToMany(Post::class, 'favorites', 'user_id', 'post_id')->withTimeStamps(); }
Laravel will assume the pivot table is post_user but since we gave the pivot table a different name (favorites), we have to pass in some additional arguments. The second argument is the name of the pivot table (favorites). The third argument is the foreign key name (user_id) of the model on which you are defining the relationship (User), while the fourth argument is the foreign key name (post_id) of the model that you are joining to (Post).
Noticed we chained withTimeStamps() to the belongsToMany(). This will allow the timestamps (create_at and updated_at) columns on the pivot table be affected whenever a row is inserted or updated.
Posts Controller
Let's create a new controller that will handle displaying posts, marking a post as favorite and unfavorite a post.
php artisan make:controller PostsController
Open the newly created app/Http/Controllers/PostsController.php and add the snippet below to it:
// app/Http/Controllers/PostsController.php // remember to use the Post model use App\Post; /** * Display a paginated list of posts. * * @return Response */ public function index() { $posts = Post::paginate(5); return view('posts.index', compact('posts')); }
The index() will get all posts and paginate them into 5 per page. Then render a view file (that we are yet to create) along with the posts, which will do the actual displaying of the posts.
Remember when we ran make:auth command that Laravel created some views. We'll be using the resources/views/layouts/app.blade.php that was created and make some few additions to it. Add the code below just after the <title>:
// resources/views/layouts/app.blade.php <link rel="stylesheet" href="http://ift.tt/2mrbfp2; />
Then add this just before the Logout list item:
// resources/views/layouts/app.blade.php <li> <a href="http://ift.tt/1uaQUM0">My Favorites</a> </li>
Now let's create the index view. Create a new posts folder within views directory and create a new index.blade.php file within the newly created folder. Paste the code below into resources/views/posts/index.blade.php:
// resources/views/posts/index.blade.php @extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="page-header"> <h3>All Posts</h3> </div> @forelse ($posts as $post) <div class="panel panel-default"> <div class="panel-heading"> </div> <div class="panel-body"> </div> </div> @empty <p>No post created.</p> @endforelse </div> </div> </div> @endsection
Pretty simple markup that displays a paginated list of posts. Open the homepage in your browser, you should see page like the image below:
Next, let's go back to PostsController and add the methods that will handle marking a post as favorite and unfavorite a post. Add the code below to PostsController:
// app/Http/Controllers/PostsController.php // remember to use use Illuminate\Support\Facades\Auth; /** * Favorite a particular post * * @param Post $post * @return Response */ public function favoritePost(Post $post) { Auth::user()->favorites()->attach($post->id); return back(); } /** * Unfavorite a particular post * * @param Post $post * @return Response */ public function unFavoritePost(Post $post) { Auth::user()->favorites()->detach($post->id); return back(); }
The favoritePost() takes a post as an argument. Using the favorites relationship we defined above, we attach the post ID to the ID of the authenticated user then insert into the favorites table. Finally, return back to the previous page.
The unFavoritePost() is the reverse of favoritePost() which simply remove the ID of the authenticated user along with the post ID from the favorites table.
Integrating With VueJs
It's time to integrate Vue into our application. We'll make the favorite button/icon a Vue component. Making it a Vue component will allow for reuse in multiple places with our application.
Once the favorite button/icon is clicked, we'll mark the post as favorite or unfavorite without reloading the page, that is through AJAX. For this, we'll make use of Axios which is a Promise based HTTP client for the browser and node.js.
Creating The Favorite Component
Create a new Favorite.vue file within the resources/assets/js/components folder and paste the code below into it:
// resources/assets/js/components/Favorite.vue <template> <span> <a href="#" v-if="isFavorited" @click.prevent="unFavorite(post)"> <i class="fa fa-heart"></i> </a> <a href="#" v-else @click.prevent="favorite(post)"> <i class="fa fa-heart-o"></i> </a> </span> </template> <script> export default { props: ['post', 'favorited'], data: function() { return { isFavorited: '', } }, mounted() { this.isFavorited = this.isFavorite ? true : false; }, computed: { isFavorite() { return this.favorited; }, }, methods: { favorite(post) { axios.post('/favorite/'+post) .then(response => this.isFavorited = true) .catch(response => console.log(response.data)); }, unFavorite(post) { axios.post('/unfavorite/'+post) .then(response => this.isFavorited = false) .catch(response => console.log(response.data)); } } } </script>
The Favorite component has two sections: template and script. In the template section, we defined the markup that will be rendered when the component is used. We are using conditional rendering to show the appropriate button/icon. That is, if isFavorited is true, the button/icon should be marked as favorite and on click of the button/icon should trigger unFavorite(). Else the button/icon should be marked as unfavorite and on click of the button/icon should trigger favorite().
Moving on to the script section, we defined some properties for the component; post (will be the ID of the post) and favorited (will either be true or false depending on if the post has been favorited by the authenticated user). We also defined an isFavorited data which will be used for the conditional rendering from above.
When the component is mounted, we set the value of isFavorited to the value of isFavorite computed property. That is, the isFavorite computed property will return the value of favorited prop which will either be true or false. We use a computed property so as to reactively get the value of the favorited prop instead using the value of favorited prop that was passed directly.
Lastly, we defined two methods: favorite() and unFavorite() which both accepts the post prop as arguments. Using Axios, we make a POST request to the routes we defined earlier. For the favorite(), once the POST request is successful, we set isFavorited to true and otherwise console log the errors. Same is applicable to the unFavorite() just that we set isFavorited to false.
Registering The Favorite Component
Before we can start to use the Favorite component, we need to first register it on our Vue root instance. Open resources/assets/js/app.js, you will see that Laravel register an Example component. We are going to replace that with the Favorite component:
// resources/assets/js/app.js Vue.component('favorite', require('./components/Favorite.vue'));
Now we can compile and build our styles and scripts:
npm run dev
Using The Favorite Component
We can now use the Favorite component. Open resources/views/posts/index.blade.php and add the snippets below to it after the closing div of the panel-body:
// resources/views/posts/index.blade.php @if (Auth::check()) <div class="panel-footer"> <favorite :post= :favorited= ></favorite> </div> @endif
The favorite button/icon will only be displayed to authenticated users. As you can see, we passed to the Favorite component the props that we defined when we created the component. To know if a post is has been favorited by the authenticated user, we call a favorited() (which we are yet to create) on the post.
To create favorited(), open app/Post.php and add the code below to it:
// app/Post.php // remember to use use App\Favorite; use Illuminate\Support\Facades\Auth; /** * Determine whether a post has been marked as favorite by a user. * * @return boolean */ public function favorited() { return (bool) Favorite::where('user_id', Auth::id()) ->where('post_id', $this->id) ->first(); }
This gets and casts to boolean the first result where the user_id is equal to that of the authenticated user and where the post_id is equal to the ID of the post the method is called on.
If you visit the homepage of the application in the browser and login, you should get something similar to:
As you can see I have marked some posts as favorites.
Displaying User Favorite Posts
Won't it be nice for users to be able to see all the posts they have marked as favorites? Sure it will be. Remember we defined a my_favorites route that will be accessible to only authenticated users, this is where users will be able to see the posts they've marked as favorites.
Let's create a UsersController that will handle this route.
php artisan make:controller UsersController
Open app/Http/Controllers/UsersController.php and add the code below to it:
// app/Http/Controllers/UsersController.php // remember to use use Illuminate\Support\Facades\Auth; /** * Get all favorite posts by user * * @return Response */ public function myFavorites() { $myFavorites = Auth::user()->favorites; return view('users.my_favorites', compact('myFavorites')); }
The myFavorites() uses the favorites relationship we defined earlier, get all the posts that the authenticated user has marked as favorites. Then return a view along with favorites posts.
Now let's create the view. Create a new users folder within the resources/views directory and within the users folder, create a new file my_favorites.blade.php and paste the code below to it:
// resources/views/users/my_favorites.blade.php @extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="page-header"> <h3>My Favorites</h3> </div> @forelse ($myFavorites as $myFavorite) <div class="panel panel-default"> <div class="panel-heading"> </div> <div class="panel-body"> </div> @if (Auth::check()) <div class="panel-footer"> <favorite :post= :favorited= ></favorite> </div> @endif </div> @empty <p>You have no favorite posts.</p> @endforelse </div> </div> </div> @endsection
The markup is similar to that of index.blade.php. As you can see, we also used the Favorite component. When viewed in the browser, you should see something similar to:
Conclusion
That's it, we are done building the Post app and seen how to allow only authenticated users mark/unmark posts as favorites without reloading the page using VueJs and Axios. I hope you find this tutorial useful. If you encounter any problems following this tutorial or have questions/suggestions, kindly drop them in the comment section below. Also, I have made a vue-favorite component based on this tutorial which can be installed through NPM.
via Scotch.io http://ift.tt/2mptpr0
0 notes